package com.fallenpanda.location.manager;

import android.app.Application;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import com.fallenpanda.location.bean.MyLocation;
import com.fallenpanda.location.utils.StringUtils;

import junit.framework.Assert;

import java.util.ArrayList;
import java.util.List;

/**
 * 定位管理器
 * ============================================================================
 * 版权所有 2014 。
 *
 * @author fallenpanda
 *
 * @version 1.0 2014-12-04
 * ============================================================================
 */
public class MainLocationManager implements MainLocationListener {

    private static final String TAG = "MainLocationManager";

    public static final String BAIDU_PROVIDER = "baidu";

    private static final int TYPE_LOCATION_CHANGED = 1;
    private static final int TYPE_LOCATION_FAIL = 2;
    private static final int TYPE_STATUS_CHANGED = 3;
    private static final int TYPE_PROVIDER_ENABLED = 4;
    private static final int TYPE_PROVIDER_DISABLED = 5;

    public static final int MODEL_ONCE = 1;//定位类型|一次
    public static final int MODEL_AUTO = 2;//定位类型|间隔

    private static final int ENOUGH_TIME = 5*1000;//定位结果有效时间
    private static final int ENOUGH_ACCURACY = 200;//定位结果有效误差

    private static Application mContext;
    private static MainLocationManager instance;

    private Handler mHandler;

    private List<MainLocationListener> listListener;
    private List<MyLocation> listLocation;
    private MyLocation lastLocation;

    private int curMode;//MODEL_ONCE | MODEL_AUTO
    private boolean curIsNeedAddress;

    private static BaiduLocationManager mBaiduLocationManager;

    private MainLocationManager(Application context) {
        mContext = context;
        listLocation = new ArrayList<MyLocation>();
        listListener = new ArrayList<MainLocationListener>();
        mHandler = new MyHandler();
    }

    public static void init(Application context){
        instance = new MainLocationManager(context);
    }

    public static void destroy(){
        if(mBaiduLocationManager != null)
            mBaiduLocationManager.destroy();
    }

    public static MainLocationManager getInstance() {
        Assert.assertNotNull("请先在AppContext中调用init()方法初始化", mContext);
        Assert.assertNotNull("请先在AppContext中调用init()方法初始化", instance);
        return instance;
    }

    private class MyHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case TYPE_LOCATION_CHANGED://位置改变
                    if(listListener!=null&&listListener.size()>0){
                        for(MainLocationListener listener:listListener){
                            listener.onLocationChanged(lastLocation);
                        }
                    }else{
                        stopLocationAll();
                    }
                    break;
                case TYPE_LOCATION_FAIL://定位失败
                    if(listListener!=null&&listListener.size()>0){
                        for(MainLocationListener listener:listListener){
                            listener.onLocationFail(msg.obj.toString());
                        }
                    }
                    stopLocationAll();
                    break;
                case TYPE_STATUS_CHANGED://状态改变

                    break;
                case TYPE_PROVIDER_ENABLED://开启

                    break;
                case TYPE_PROVIDER_DISABLED://关闭

                    break;
                default:
                    break;
            }
        }
    }

    public void registerListener(MainLocationListener listener){
        if (listListener!=null&&!listListener.contains(listener))
            listListener.add(listener);
    }

    public void unregisterListener(MainLocationListener listener){
        if (listListener!=null&&listListener.contains(listener))
            listListener.remove(listener);
    }

    @Override
    public void onLocationChanged(MyLocation location) {
        Log.i(TAG,"onLocationChanged");
        if(curIsNeedAddress){
            addLocation(location);
        }else if (isBetterLocation(location, lastLocation)){
            addLocation(location);
        }
        mHandler.sendEmptyMessage(TYPE_LOCATION_CHANGED);
    }

    @Override
    public void onLocationFail(String provider) {
        Log.i(TAG, "onLocationFail:" + provider);
        Message msg = Message.obtain();
        msg.what = TYPE_LOCATION_FAIL;
        msg.obj = provider;
        mHandler.sendMessage(msg);
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
        Message msg = Message.obtain();
        msg.what = TYPE_STATUS_CHANGED;
        Bundle b = new Bundle();
        b.putString("provider", provider);
        b.putInt("status", status);
        if (extras != null) {
            b.putBundle("extras", extras);
        }
        msg.obj = b;
        mHandler.sendMessage(msg);
    }

    @Override
    public void onProviderEnabled(String provider) {
        Message msg = Message.obtain();
        msg.what = TYPE_PROVIDER_ENABLED;
        msg.obj = provider;
        mHandler.sendMessage(msg);
    }

    @Override
    public void onProviderDisabled(String provider) {
        Message msg = Message.obtain();
        msg.what = TYPE_PROVIDER_DISABLED;
        msg.obj = provider;
        mHandler.sendMessage(msg);
    }

    /**
     * 初始化百度定位
     */
    public void initBaiduLocation(){
        if(mBaiduLocationManager==null)
            mBaiduLocationManager = new BaiduLocationManager(mContext,this);//百度定位
    }

    /**
     * 定位一次（百度）
     *
     * @param isNeedAddress 是否需要地址信息
     */
    public void getBaiduLocationOnce(boolean isNeedAddress){
        getLocation(BAIDU_PROVIDER, MODEL_ONCE, 0, isNeedAddress);
    }

    /**
     * 定位多次（百度）
     *
     * @param scanSpan 时间间隔
     */
    public void getBaiduLocationAuto(int scanSpan){
        getLocation(BAIDU_PROVIDER, MODEL_AUTO, scanSpan, false);
    }

    /**
     * 停止定位
     */
    public void stopBaiduLocation(){
        stopLocation(BAIDU_PROVIDER);
    }

    private void getLocation(String provider,int mode,int scanSpan, boolean isNeedAddress){
        Log.i(TAG, "getLocation:"+provider+"|"+mode+"|"+scanSpan+"|"+isNeedAddress);
        if(StringUtils.isNotEmpty(provider)){
            this.curMode = mode;
            this.curIsNeedAddress = isNeedAddress;
            if(BAIDU_PROVIDER.equals(provider)){
                initBaiduLocation();
                switch (mode){
                    case MODEL_ONCE:
                        mBaiduLocationManager.getLocationOnce(isNeedAddress);
                        break;
                    case MODEL_AUTO:
                        mBaiduLocationManager.getLocationAuto(scanSpan);
                        break;
                }
            }
        }
    }

    private void stopLocation(String provider){
        Log.i(TAG, "stopLocation:"+provider);
        if(StringUtils.isNotEmpty(provider)){
            if(BAIDU_PROVIDER.equals(provider)){
                if(mBaiduLocationManager!=null)
                    mBaiduLocationManager.stop();
            }
        }
    }

    private void stopLocationAll(){
        if(mBaiduLocationManager!=null)
            mBaiduLocationManager.stop();
    }

    private void addLocation(MyLocation location){
        lastLocation = location;
        if (listLocation.size() == 10)
            listLocation.remove(9);
        listLocation.add(0, location);
    }

    private MyLocation getLastLocation(){
        return lastLocation;
    }

    /**
     * 是否为更准确的定位结果
     * @param location
     * @param targetLocation 目标
     * @return
     */
    public static boolean isBetterLocation(MyLocation location, MyLocation targetLocation) {
        if(location!=null){
            if(targetLocation == null){
                return true;
            }
            //间隔时间
            long time = location.getmTime() - targetLocation.getmTime();
            if(time > ENOUGH_TIME){
                //大于有效时间
                return true;
            }else if(time < -ENOUGH_TIME) {
                //小于有效时间
                return false;
            }else{
                //有效时间范围内
                //间隔精确度
                int accuracy = (int) (location.getmAccuracy() - targetLocation.getmAccuracy());
                if(accuracy < 0){
                    //精确度更小
                    return true;
                }else if(accuracy > ENOUGH_ACCURACY){
                    //超过有效误差范围
                    return false;
                }else{
                    //误差范围内
                    if(time > 0){
                        //时间更新的
                        return true;
                    }
                }
            }
        }
       return false;
    }

    /**
     * 判断定位方式是否一致
     * @param provider
     * @param targetProvider 目标
     * @return
     */
    public static boolean isSameProvider(String provider, String targetProvider) {
        if(StringUtils.isNotEmpty(provider)&&StringUtils.isNotEmpty(targetProvider)){
            if(provider.equals(targetProvider)){
                return true;
            }
        }
        return false;
    }

}
